﻿using DiLe.Mes.Application.Common;
using DiLe.Mes.Application.Common.Equipment;
using DiLe.Mes.Application.Common.Equipment.ViewModel;
using DiLe.Mes.Application.Handler;
using DiLe.Mes.Model.Common;
using DiLe.Mes.Model.Common.Equipment.Entity.SparePart;

namespace DiLe.Mes.Cloud.Controllers.Equipment.SparePart {
    /// <summary>
    /// 设备入库管理
    /// </summary>
    [ApiExplorerSettings(GroupName = ApiCloudGroupConst.EquipmentManage)]
    public class SparePartStockInController : ApiBaseController {

        private readonly SparePartManageClient _manageClient;
        private readonly EquipmentExjosnHandler _handler;
        private readonly SystemClient _systemClient;

        /// <summary>
        /// 构造函数
        /// </summary>
        public SparePartStockInController(SparePartManageClient sparePartManage, EquipmentExjosnHandler handler, SystemClient systemClient) {
            _manageClient = sparePartManage;
            _handler = handler;
            _systemClient = systemClient;
        }
        /// <summary>
        /// 获取入库管理列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetSparePartStockInPageList(QueryParameter parameter) {
            var whereExpression = Expressionable.Create<SparePartStockInEntity>();

            if (!parameter.Keyword.IsNullOrEmpty()) {
                whereExpression.Or(p => p.Name.Contains(parameter.Keyword));
                whereExpression.Or(p => p.Code.Contains(parameter.Keyword));
            }
            if (parameter.Pagination == null) {
                var res = await _manageClient.GetSparePartStockInListAsync(whereExpression.ToExpression());
                await _handler.FillSparePartStockInExjosn(res);
                return Success(res);
            } else {
                var res = await _manageClient.GetSparePartStockInPageListAsync(whereExpression.ToExpression(), parameter.Pagination);
                await _handler.FillSparePartStockInExjosn(res.Record);
                return Success(res);
            }
        }
        /// <summary>
        /// 获取入库管理
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> GetSparePartStockIn(long id) {
            var dto = new SparePartStockInDto();
            var res = await _manageClient.GetSparePartStockInAsync(id);
            if (res.Id > 0) {
                dto.Model = res;
                var data = await _manageClient.GetSparePartLedgerAsync(dto.Model.SparePartId);
                dto.SparePartLedgerModel = await _handler.FillSparePartLedgerExjosn(data);
            }
            await _handler.FillSparePartStockInExjosn([res]);
            return Success(dto);
        }
        /// <summary>
        /// 保存入库管理
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> SaveSparePartStockIn(SparePartStockInEntity entity) {
            if (entity.Id > 0) {
                var oldData = await _manageClient.GetSparePartStockInAsync(entity.Id);
                if (oldData.WarehouseId == entity.WarehouseId) {
                    if (oldData.StockInNumber > entity.StockInNumber) {
                        await MinusSparePartInventory(oldData.WarehouseId, oldData.SparePartId, oldData.StockInNumber - entity.StockInNumber);
                    } else {
                        await AddSparePartInventory(entity.WarehouseId, entity.SparePartId, entity.StockInNumber - oldData.StockInNumber);
                    }
                } else {
                    await MinusSparePartInventory(oldData.WarehouseId, oldData.SparePartId, oldData.StockInNumber);
                    await AddSparePartInventory(entity.WarehouseId, entity.SparePartId, entity.StockInNumber);
                }
            } else {
                await AddSparePartInventory(entity.WarehouseId, entity.SparePartId, entity.StockInNumber);
            }
            long resId = await _manageClient.SaveSparePartStockInAsync(entity);
            return resId > 0 ? Success() : Fail();
        }
        /// <summary>
        /// 删除入库管理
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> DeleteSparePartStockIn(List<long> ids) {
            var list = await _manageClient.GetSparePartStockInListAsync(p => ids.Contains(p.Id));
            await MinusSparePartInventory(list);
            var res = await _manageClient.DeleteSparePartStockInAsync(ids);
            return res ? Success() : Fail();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="warehouseId"></param>
        /// <param name="sparePartId"></param>
        /// <param name="quantity"></param>
        private async Task AddSparePartInventory(long warehouseId, long sparePartId, int quantity) {
            var inventory = await _systemClient.GetSparePartInventoryAsync(p => p.SparePartId == sparePartId && p.WarehouseId == warehouseId);
            if (inventory == null) {
                inventory = new SparePartInventoryEntity() {
                    InventoryQuantity = quantity,
                    SparePartId = sparePartId,
                    WarehouseId = warehouseId
                };
                await _systemClient.InsertSparePartInventoryAsync(inventory);
            } else {
                inventory.InventoryQuantity += quantity;
                await _systemClient.UpdateSparePartInventoryAsync([inventory]);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="warehouseId"></param>
        /// <param name="sparePartId"></param>
        /// <param name="quantity"></param>
        private async Task MinusSparePartInventory(long warehouseId, long sparePartId, int quantity) {
            var inventory = await _systemClient.GetSparePartInventoryAsync(p => p.SparePartId == sparePartId && p.WarehouseId == warehouseId);
            if (inventory != null) {
                inventory.InventoryQuantity -= quantity;
                await _systemClient.UpdateSparePartInventoryAsync([inventory]);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        private async Task MinusSparePartInventory(List<SparePartStockInEntity> list) {
            if (list.None()) {
                return;
            }
            var sparePartIds = list.Select(x => x.SparePartId).Distinct().ToList();
            var warehouseIds = list.Select(x => x.WarehouseId).Distinct().ToList();
            var inventoryList = await _systemClient.GetSparePartInventoryListAsync(p => sparePartIds.Contains(p.SparePartId) || warehouseIds.Contains(p.WarehouseId));
            var dataList = new List<SparePartInventoryEntity>();
            foreach (var item in list) {
                var inventory = inventoryList.FirstOrDefault(p => p.SparePartId == item.SparePartId && p.WarehouseId == item.WarehouseId);
                if (inventory == null) {
                    continue;
                }
                inventory.InventoryQuantity -= item.StockInNumber;
                dataList.Add(inventory);
            }
            await _systemClient.UpdateSparePartInventoryAsync(dataList);
        }
    }
}
